package interfaces.hud.targetInfos;

import interfaces.superWidgets.ListenerKeeperElement;

import java.util.HashSet;

import logic.nodes.TeamNode;
import logic.ships.carrier.Carrier;
import logic.ships.frigate.Frigate;
import logic.ships.mothership.MotherShip;
import map.spawnStation.SpawnStation;

import com.jme.math.FastMath;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.Node;
import com.jme.scene.Text;
import com.jme.scene.shape.Quad;
import com.jme.scene.state.TextureState;
import com.jme.util.AreaUtils;

import fileHandling.TextureLoader;

public class TargetAngles extends TargetInfoNode {
	
	private static final long serialVersionUID = 1L;
	
	private static HashSet<Class<?>> exceptions;
	
	private final float MARKED_SIZE = 0.7f;
	private final float NORMAL_SIZE = 0.35f;
	
	private final float MIN_SCALE = 1f;
	private final float MAX_SCALE = 220f;
	
	private final String ANGLE_PATH = "data/textures/hud/shipAngles/";
	
	private Quad lu, ru, rd, ld;
	private Quad leftUp, rightUp, rightDown, leftDown;
	private Quad leftUpM, rightUpM, rightDownM, leftDownM;
	private Node node, angleNode, missionNode;
	private boolean missionAnglesEnabled, isException;
	private Text letterText;
	
	public TargetAngles(TeamNode target, ListenerKeeperElement element) {
		super("Target Angles", target, element);
		
		if(exceptions == null) {
			exceptions = new HashSet<Class<?>>();
			exceptions.add(MotherShip.class);
			exceptions.add(SpawnStation.class);
			exceptions.add(Carrier.class);
			exceptions.add(Frigate.class);
		}
		
		isException = exceptions.contains(target.getClass());
	}
	
	@Override
	protected void init() {		
		int size = display.getWidth() / 50;
		
		String extend = "Enemy.png";
		if(isFriendly) extend = "Friend.png";
		else if(neutral) extend = "Neutral.png";
		
		angleNode = new Node("Angle Node");
		
		leftUp = new Quad("Left Up Angle", size, size);
		finishQuad(leftUp, ANGLE_PATH + "leftUp" + extend, angleNode);
		
		rightUp = new Quad("Right Up Angle", size, size);
		finishQuad(rightUp, ANGLE_PATH + "rightUp" + extend, angleNode);
		
		rightDown = new Quad("Right Down Angle", size, size);
		finishQuad(rightDown, ANGLE_PATH + "rightDown" + extend, angleNode);
		
		leftDown = new Quad("Left Down Angle", size, size);
		finishQuad(leftDown, ANGLE_PATH + "leftDown" + extend, angleNode);
		
		leftUp.setLocalScale(NORMAL_SIZE);
		rightUp.setLocalScale(NORMAL_SIZE);
		leftDown.setLocalScale(NORMAL_SIZE);
		rightDown.setLocalScale(NORMAL_SIZE);
		
		missionNode = new Node("Mission Node");
		extend = "Mission.png";
		
		leftUpM = new Quad("Left Up Mission", size, size);
		finishQuad(leftUpM, ANGLE_PATH + "leftUp" + extend, missionNode);
		
		rightUpM = new Quad("Right Up Mission", size, size);
		finishQuad(rightUpM, ANGLE_PATH + "rightUp" + extend, missionNode);
		
		rightDownM = new Quad("Right Down Mission", size, size);
		finishQuad(rightDownM, ANGLE_PATH + "rightDown" + extend, missionNode);
		
		leftDownM = new Quad("Left Down Mission", size, size);
		finishQuad(leftDownM, ANGLE_PATH + "leftDown" + extend, missionNode);
		
		leftUpM.setLocalScale(MARKED_SIZE);
		rightUpM.setLocalScale(MARKED_SIZE);
		leftDownM.setLocalScale(MARKED_SIZE);
		rightDownM.setLocalScale(MARKED_SIZE);
		
		updateRenderState();
		
		missionAnglesEnabled = true;
		activateMissionAngles(false);
	}
	
	public void initStationLetter() {
		assert(isSpawnStation());
		
		SpawnStation station = (SpawnStation)target;
		String name = "Station Letter for " + station.getStationLetter();
		letterText = Text.createDefaultTextLabel(name, station.getStationLetter());
		
		updateLetterText();
	}
	
	private void finishQuad(Quad quad, String texturePath, Node node) {		
		TextureState texState = TextureLoader.getTextureState(texturePath);
		
		quad.setRenderState(texState);
		quad.updateRenderState();
		
		node.attachChild(quad);
	}
	
	@Override
	public void teamChanged() {
		super.teamChanged();
		
		detachChild(node);
		
		init();
	}
	
	@Override
	public void setMarked(boolean marked) {
		super.setMarked(marked);
		
		float size = NORMAL_SIZE;
		if(marked) size = MARKED_SIZE;
		
		leftUp.setLocalScale(size);
		rightUp.setLocalScale(size);
		leftDown.setLocalScale(size);
		rightDown.setLocalScale(size);
	}
	
	public void activateMissionAngles(boolean enable) {
		if(missionAnglesEnabled == enable) return;
		
		detachChild(node);
		if(enable) {
			lu = leftUpM;
			ld = leftDownM;
			ru = rightUpM;
			rd = rightDownM;
			node = missionNode;
		} else {
			lu = leftUp;
			ld = leftDown;
			ru = rightUp;
			rd = rightDown;
			node = angleNode;
		}
		
		attachChild(node);
		
		missionAnglesEnabled = enable;
		
		if(isSpawnStation() && letterText != null) updateLetterText();
	}
	
	protected void updateLetterText() {
		assert(isSpawnStation());
		
		ColorRGBA color = ColorRGBA.red;
		if(isFriendly) color = ColorRGBA.green;
		else if(neutral) color = ColorRGBA.gray;
		
		if(missionAnglesEnabled) color = ColorRGBA.magenta;
		letterText.setTextColor(color);
		letterText.updateRenderState();
		
		node.attachChild(letterText);
	}
	
	protected boolean isSpawnStation() { return target instanceof SpawnStation; }
	
	@Override
	public void update() {
		if(cam == null) {
			cam = target.getIngameState().getCam();
			if(cam == null) return;
		}
		
		if(target.getBound() == null || (!target.isVisibleToPlayer() && !isException && !marked)) {
			detachChild(node);
			return;
		}
		
		Vector3f targetPos = target.getLocalTranslation();
		Vector3f screenPos = display.getScreenCoordinates(targetPos);
		
		if(target.getParent() == null || target.isDestroyed() || screenPos.z >= 1 || screenPos.x < 0 
		|| screenPos.x > display.getWidth() || screenPos.y < 0 || screenPos.y > display.getHeight()) {
			detachChild(node);
			return;
		}
		
		float distance = targetPos.distance(cam.getLocation());
		float area = AreaUtils.calcScreenArea(target.getBound(), distance, display.getWidth());
		float scale = FastMath.sqrt(area) * 0.6f;
		
		if(scale > MAX_SCALE) {
			detachChild(node);
			return;
		}
		
		if(scale < MIN_SCALE) scale = MIN_SCALE;
		
		attachChild(node);
		
		lu.getLocalTranslation().set(-scale, scale, 0f);
		ld.getLocalTranslation().set(-scale, -scale, 0f);
		ru.getLocalTranslation().set(scale, scale, 0f);
		rd.getLocalTranslation().set(scale, -scale, 0f);
		if(isSpawnStation()) {
			float x = letterText.getWidth() / 2;
			letterText.getLocalTranslation().set(- x, scale, 0f);
		}
		
		getLocalTranslation().set(screenPos.x, screenPos.y, 0f);
	}
}